package cn.tedu.controller;

import cn.tedu.util.RedisConstant;
import cn.tedu.vo.JsonResult;
import cn.tedu.vo.UserPointVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 实时榜单接口
 * @author Kiven
 */
@RestController
@RequestMapping("/api/v1/realTimeRank")
@Api(tags = {"实时榜单接口"})
public class RealTimeListController {


    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 查询榜单由大到小
     * @return
     */
    @GetMapping("/listDesc")
    @ApiOperation(value = "查询榜单由大到小", notes = "查询榜单由大到小")
    public JsonResult findUserPointRealTimeRankDesc(){
        BoundZSetOperations<String, UserPointVO> operations = redisTemplate.boundZSetOps(RedisConstant.REAL_TIME_RANK);
        Set<UserPointVO> userPointVOS = operations.reverseRange(0, -1);
        return JsonResult.success("查询成功",userPointVOS);
    }

    /**
     * 查询榜单由小到大
     * @return
     */
    @GetMapping("/listAsc")
    @ApiOperation(value = "查询榜单由小到大", notes = "查询榜单由小到大")
    public JsonResult findUserPointRealTimeRankAsc(){
        BoundZSetOperations<String, UserPointVO> operations = redisTemplate.boundZSetOps(RedisConstant.REAL_TIME_RANK);
        Set<UserPointVO> userPointVOS = operations.range(0,-1);
        return JsonResult.success("查询成功",userPointVOS);
    }

    /**
     * 查询榜单由大到小,支持选取名次范围
     * @return
     */
    @GetMapping("/listDescLimit")
    @ApiOperation(value = "查询榜单由大到小,支持选取名次范围", notes = "查询榜单由大到小,支持选取名次范围")
    public JsonResult findUserPointRealTimeRankDescLimit(int startSize,int endSize){
        BoundZSetOperations<String, UserPointVO> operations = redisTemplate.boundZSetOps(RedisConstant.REAL_TIME_RANK);
        Set<UserPointVO> userPointVOS = operations.reverseRange(startSize,endSize);
        return JsonResult.success("查询成功",userPointVOS);
    }

    /**
     * 查询榜单由小到大,支持选取名次范围
     * @return
     */
    @GetMapping("/listAscLimit")
    @ApiOperation(value = "查询榜单由小到大,支持选取名次范围", notes = "查询榜单由小到大,支持选取名次范围")
    public JsonResult findUserPointRealTimeRankAscLimit(int startSize,int endSize){
        BoundZSetOperations<String, UserPointVO> operations = redisTemplate.boundZSetOps(RedisConstant.REAL_TIME_RANK);
        Set<UserPointVO> userPointVOS = operations.range(startSize,endSize);
        return JsonResult.success("查询成功",userPointVOS);
    }

    @GetMapping("/getUserScoreRankDesc")
    @ApiOperation(value = "查询个人得分名次", notes = "根据手机号码+用户名才能查到,分数越大名次越高")
    public JsonResult findUserPointRankDesc(UserPointVO userPointVO){
        BoundZSetOperations<String, UserPointVO> operations = redisTemplate.boundZSetOps(RedisConstant.REAL_TIME_RANK);
        Long aLong = operations.reverseRank(userPointVO);
        if(aLong==null){
            throw new RuntimeException("该用户不存在,请输入用户名+手机");
        }
        return JsonResult.success("查询该用户名次成功",++ aLong);
    }
    @GetMapping("/getUserScoreRankAsc")
    @ApiOperation(value = "查询个人得分名次", notes = "根据手机号码+用户名才能查到,分数越小名次越高")
    public JsonResult findUserPointRankAsc(UserPointVO userPointVO){
        BoundZSetOperations<String, UserPointVO> operations = redisTemplate.boundZSetOps(RedisConstant.REAL_TIME_RANK);
        Long aLong = operations.rank(userPointVO);
        if(aLong==null){
            throw new RuntimeException("该用户不存在,请输入用户名+手机");
        }
        return JsonResult.success("查询该用户名次成功",++ aLong);
    }
    /**
     * 查询用户分数
     * 获取zset集合里面的某个元素是根据hash,equlas计算结果来的.可以重写equlasandhashcode 手机号一样即可此处没有变动
     * 根据手机号码+用户名才能查到
     * @return
     */
    @GetMapping("/getScore")
    @ApiOperation(value = "查询个人得分", notes = "根据手机号码+用户名才能查到")
    public JsonResult findUserPoint(UserPointVO userPointVO){
        BoundZSetOperations<String, UserPointVO> operations = redisTemplate.boundZSetOps(RedisConstant.REAL_TIME_RANK);
        Double score = operations.score(userPointVO);
        return JsonResult.success("查询成功",score);
    }

    /**
     * 修改分数 添加或者减少,如果需要减少分数则传入负数即可
     * @param userPointVO
     * @param score
     * @return 返回当前修改的分数和排行榜的最新数据
     */
    @PostMapping
    @ApiOperation(value = "新增修改分数接口", notes = "提供用户姓名,手机和分数实现新增或者修改分数,分数可以为负数,返回当前修改的分数和排行榜的最新数据")
    public JsonResult updateUserPoint(UserPointVO userPointVO,Double score){
        BoundZSetOperations<String, UserPointVO> operations = redisTemplate.boundZSetOps(RedisConstant.REAL_TIME_RANK);
        // 取出原来的分数 score为负数则为减少 为正数则为增加 如果没有该行则增加一行
        score = operations.incrementScore(userPointVO, score);
        Set<UserPointVO> userPointVOS = operations.reverseRange(0, -1);
        Map<String,Object> map = new HashMap<>();
        map.put("score",score);
        map.put("list",userPointVOS);
        return JsonResult.success("得分,当前分数"+score,map);
    }

    /**
     * 删除某个用户的得分,万一死了呢
     * @param userPointVO
     * @return
     */
    @DeleteMapping
    public JsonResult deleteUserPoint(UserPointVO userPointVO){
        BoundZSetOperations<String, UserPointVO> operations = redisTemplate.boundZSetOps(RedisConstant.REAL_TIME_RANK);
        operations.remove(userPointVO);
        return JsonResult.success("删除成功");
    }

}
